/**
 * 
 */
package de.cbf.cam.dsa.inventory.composites;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;

import de.cbf.cam.dsa.inventory.interfaces.IItemDragSource;
import de.cbf.cam.dsa.model.entities.Ground;
import de.cbf.cam.dsa.model.entities.items.Item;
import de.cbf.cam.dsa.model.util.Position3f;

/**
 * @author Nebelritter
 *
 */
public class CompositeGround extends Composite implements IItemDragSource {

	private static CompositeGround instance = null;
	
	private Ground ground = null;
	
	private Table tableGround; 
	
	/**
	 * @param parent
	 * @param style
	 */
	public CompositeGround(Composite parent, int style) {
		super(parent, style);		
		ground = Ground.getInstance();
		if(ground != null){
			instance = this;
			ground.propertyChangeSupport.addPropertyChangeListener(new ItemOnGroundChange());
			
			tableGround = new Table(this, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL|SWT.MULTI | SWT.FULL_SELECTION);
			tableGround.setLayoutData(new GridData(GridData.FILL_BOTH));
			tableGround.setLinesVisible(true);
			tableGround.setHeaderVisible(true);
			
			buildDragSource();
			
			buildDropTarget();
		}
	}

	private void buildDropTarget() {

		Transfer[] types = new Transfer[] {TextTransfer.getInstance() };
		
		DropTarget target = new DropTarget(tableGround, DND.DROP_MOVE|DND.DROP_LINK|DND.DROP_DEFAULT);
	    target.setTransfer(types);
	    
	    target.addDropListener(new GroundDropTargetListener());
		
	}

	private void buildDragSource() {
		Transfer[] types = new Transfer[] { TextTransfer.getInstance()};
	    DragSource source = new DragSource(tableGround, DND.DROP_LINK|DND.DROP_MOVE);
	    source.setTransfer(types);
	   
	    source.addDragListener(new GroundDragSourceListener());	
		
	}

	private void fillTable(){
		
	}
	
	public void addItem(Item item,Position3f position){
		ground.addItemToGround(item, position);
	}
	
	public boolean removeItem(Item item){
		return ground.removeItem(item);
	}
	
	@Override
	public Item getItemByGUID(String guid) {
		return ground.getItemByGUID(guid);
	}

	public static IItemDragSource getInstance() {		
		return instance;
	}

	@Override
	public void dispose() {		
		super.dispose();
		instance = null;
		if(ground != null){		
			ground.propertyChangeSupport.removePropertyChangeListener(new ItemOnGroundChange());
		}
	}

	private class ItemOnGroundChange implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			fillTable();			
		}		
	}
	private class GroundDragSourceListener extends DragSourceAdapter{
		public void dragSetData(DragSourceEvent event) {	
			  
			// Get the selected items in the drag source
			DragSource ds = (DragSource) event.widget;
			Table table = (Table) ds.getControl();
			TableItem[] selection = table.getSelection();	        
			  
			//get guid of selected item which will be transferred 
			Item item = (Item)selection[0].getData();
			if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
				event.data = item.getGuid();// store  item guid 
//				System.out.println("GUID set: "+item.getGuid());
			}				  
		}

		@Override
		public void dragFinished(DragSourceEvent event) {				  
			if (event.detail == DND.DROP_MOVE){
				System.out.println("Drag ended in MOVE"); //delete item and all items in container
				fillTable();
			}
			if (event.detail == DND.DROP_LINK){
				System.out.println("Drag ended in LINK"); //refill table for changed wear /or notified via listener
				fillTable();
			}				 
		}
	}
	
	private class GroundDropTargetListener extends DropTargetAdapter{
		private TextTransfer textTransfer = TextTransfer.getInstance();
		
		public void dragEnter(DropTargetEvent event) {		       	
			if (event.detail == DND.DROP_DEFAULT) {
				boolean operationAllowed = false;
				if ((event.operations & DND.DROP_LINK) != 0) {
		            event.detail = DND.DROP_LINK;
		            operationAllowed = true;
	 	        } 
   			if ((event.operations & DND.DROP_MOVE) != 0) {
		        event.detail = DND.DROP_MOVE;
		        	operationAllowed = true;
	 	        }	    			
   				if(!operationAllowed){
   					event.detail = DND.DROP_NONE;
   				}
	 	    }		 	    
		}	    		
   	
		public void dragOver(DropTargetEvent event) {			
			event.feedback = DND.FEEDBACK_SCROLL;	       
		}
     
		public void drop(DropTargetEvent event) {
			if (textTransfer.isSupportedType(event.currentDataType)) {
	            String guid = (String)event.data;
	            
	            Item item = null;
	           
	            if((event.detail&DND.DROP_LINK)==DND.DROP_LINK){
	            	//want to perform LINK operation -> item already here(should)
	            	item = getItemByGUID(guid);
	            	if(item == null){System.out.println("try to find item for LINK that is not present\n" +
	            				"GUID: "+guid);
	            	}
	            }
	            //if not -> add it as item 
	            if((event.detail&DND.DROP_MOVE)==DND.DROP_MOVE){
	            	
								
	            }	 	           	 	            
	            
	            fillTable();
	        }		        		
		}
		
		@Override
		public void dragOperationChanged(DropTargetEvent event) {
			 if (event.detail == DND.DROP_DEFAULT) {
   			 boolean operationAllowed = false;
   			 if ((event.operations & DND.DROP_LINK) != 0) {
		             event.detail = DND.DROP_LINK;
		             operationAllowed = true;
	 	         } 
   			 if ((event.operations & DND.DROP_MOVE) != 0) {
		             event.detail = DND.DROP_MOVE;
		             operationAllowed = true;
	 	         }	    			
   			 if(!operationAllowed){
   				 event.detail = DND.DROP_NONE;
   			 }
	 	     }		      
		}	
		
		
	}
}
